const doio = require('doio');
const logger = require('doio-logger');
const doioproxy = require('doio-proxy');
const monitor = require('doio-monitor');
const doioloader = require('doio-loader');
const titbitloader = require('titbit-loader');
const gohttp = require('gohttp');
const titbit = require('titbit');
const fs = require('fs');
const tls = require('tls');

class ant {

  constructor (options = null) {

    this.options = {
      doio:{
        debug: true
      },
      
      logger: {},

      monitor: {
        type: 'text',
        file: 'doio-monitor.log'
      },

      loader:{}

    };

    if (!options && typeof options !== 'object') {
      this.options = options;
    }

    if (options && typeof options === 'object') {
      this.setOptions('doio', options);
      this.setOptions('loader', options);
      this.setOptions('monitor', options);
      this.setOptions('logger', options);
    }

    this.doio = new doio(this.options.doio);

    this.router = this.doio.router;

    let mth = '';
    for (let k in this.doio.router.apiTable) {
      mth = k.toLowerCase();
      this[mth] = this.doio.router[mth].bind(this.doio.router);
    }
    this.map = this.doio.router.map.bind(this.doio.router);
    this.any = this.doio.router.any.bind(this.doio.router);

    this.use = this.doio._midware.use.bind(this.doio._midware);
    this.pre = this.doio.pre.bind(this.doio);

    this.logger = null;

    if (this.options.logger !== undefined && this.options.logger !== false) {
      this.logger = new logger(this.options.logger);
      this.logger.init(this.doio);
    }

    this.monitor = null;

    if (this.options.monitor !== undefined && this.options.monitor !== false) {
      this.monitor = new monitor(this.options.monitor);
      this.monitor.init(this.doio);
    }

    this.loader = null;
    if (this.options.loader !== undefined && this.options.loader !== false) {
      this.loader = new doioloader(this.options.loader);
      this.loader.init(this.doio);
    }

  }

  setOptions (key, opts) {
    if (!opts || typeof opts !== 'object') {
      return;
    }

    if (opts[key] === undefined || opts[key] === null || typeof opts[key] !== 'object') {
      return;
    }

    for (let k in opts[key]) {
      this.options[key][k] = opts[key][k];
    }

  }

  debug (b = true) {
    this.doio.config.debug = b;
    return this;
  }

  start (port = 2022, host = '0.0.0.0', workers = 0) {
    this.doio.printRoute();
    return this.doio.daemon(port, host, workers);
  }

}

class tlsni {

  constructor (certs = {}) {
    this.certs = {};

    if (typeof certs !== 'object') {
      throw new Error('必须传递key-value形式的配置，key是域名，value是证书路径');
    }

    let t = '';
    for (let h in certs) {
      t = certs[h];
      if (t.key === undefined || t.cert === undefined) {
        console.error(`${h} 没有设置key和cert`);
        continue;
      }

      try {
        this.certs[h] = {
          key : fs.readFileSync(t.key),
          cert : fs.readFileSync(t.cert)
        }
      } catch (err) {
        console.error(h, err.message);
        continue;
      }

    }
  }

  init (app) {
    let self = this;
    app.config.server.SNICallback = (servername, cb) => {
      return cb(null, tls.createSecureContext(self.certs[servername]) );
    };
  }

}

module.exports = {
  ant,
  tlsni,
  doio,
  logger,
  monitor,
  dloader : doioloader,
  tloader : titbitloader,
  hc      : gohttp,
  titbit  : titbit,
  dproxy  : doioproxy,
};
